﻿// stl_test_01.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <vector>
#include <array>
#include <deque>
/*
主要练习 vector array容器 deque容器

*/
class stlExample
{
public:
	void testInsert();
	void testItera();
	void testArr(); //array 容器
	void testVec();
	void testDeq();

};

void stlExample::testInsert() {
//容器库 array vector
//insert()
//insert() 函数的功能是在 vector 容器的指定位置插入一个或多个元素。该函数的语法格式有多种，如表 1 所示。
	std::vector<int> demo{ 1,2 };
	demo.insert(demo.begin() + 1, 3); // 1,3,2

	demo.insert(demo.end(), 2, 5); // 1,3,2,5,5

	//插入其他迭代器
	std::array<int, 3>test{ 7,8,9 };
	demo.insert(demo.end(), test.begin(), test.end()); //{1,3,2,5,5,7,8,9}

	demo.insert(demo.end(), { 10,11 });//{1,3,2,5,5,7,8,9,10,11}

	for (size_t i = 0; i < demo.size(); i++)
	{
		std::cout << demo.at(i) << " ";
	}
}

void stlExample::testItera() {
	/*
array	随机访问迭代器 数组容器
vector	随机访问迭代器 向量容器
deque	随机访问迭代器 双向队列容器
list	双向迭代器    链表容器
set / multiset	双向迭代器
map / multimap	双向迭代器
forward_list	前向迭代器
unordered_map / unordered_multimap	前向迭代器
unordered_set / unordered_multiset	前向迭代器
stack	不支持迭代器
queue	不支持迭代器
正向迭代器	    容器类名::iterator  迭代器名;
常量正向迭代器	容器类名::const_iterator  迭代器名;
反向迭代器	    容器类名::reverse_iterator  迭代器名;
常量反向迭代器	容器类名::const_reverse_iterator  迭代器名;

通过定义以上几种迭代器，就可以读取它指向的元素，*迭代器名就表示迭代器指向的元素。其中，常量迭代器和非常量迭代器的分别在于，通过非常量迭代器还能修改其指向的元素。
另外，反向迭代器和正向迭代器的区别在于：
对正向迭代器进行 ++ 操作时，迭代器会指向容器中的后一个元素；
而对反向迭代器进行 ++ 操作时，迭代器会指向容器中的前一个元素。
	*/
	std::vector<int> v{ 1,2,3,4,5,6,7,8,9,10 };
	for (size_t i = 0; i < v.size(); i++)
	{
		std::cout << v[i] << " ";
	}

	std::cout << "第二张遍历方法:" << std::endl;
	//创建迭代器  比较迭代器
	std::vector<int>::iterator i;

	for (i = v.begin(); i != v.end(); ++i)
	{
		std::cout << *i << " ";
	}

	std::cout << std::endl << "第三种遍历方法" << std::endl;
	for (i = v.begin(); i < v.end(); ++i)
	{
		std::cout << *i << " ";
	}

}

void stlExample::testArr() {

	std::array<int, 4> values{};

	//初始化容器
	for (int i = 0; i < values.size(); i++)
	{
		values.at(i) = i;
	}
	//使用Get重载函数输出元素
	std::cout << std::get<3>(values) << std::endl;

	//如果容器不是空，则输出容器所有元素
	//auto 关键字，可以使编译器自动判定变量的类型
	if (!values.empty())
	{
		for (auto va1 = values.begin(); va1 < values.end(); va1++)
		{
			std::cout << *va1 << " ";
		}
	}
}

void stlExample::testVec() {
	//vector 遍历
	/*
pop_back()	删除 vector 容器中最后一个元素，该容器的大小（size）会减 1，但容量（capacity）不会发生改变。
erase(pos)	删除 vector 容器中 pos 迭代器指定位置处的元素，并返回指向被删除元素下一个位置元素的迭代器。该容器的大小（size）会减 1，但容量（capacity）不会发生改变。
swap(beg)、pop_back()	先调用 swap() 函数交换要删除的目标元素和容器最后一个元素的位置，然后使用 pop_back() 删除该目标元素。
erase(beg,end)	删除 vector 容器中位于迭代器 [beg,end)指定区域内的所有元素，并返回指向被删除区域下一个位置元素的迭代器。该容器的大小（size）会减小，但容量（capacity）不会发生改变。
remove()	删除容器中所有和指定元素值相等的元素，并返回指向最后一个元素下一个位置的迭代器。值得一提的是，调用该函数不会改变容器的大小和容量。
clear()	删除 vector 容器中所有的元素，使其变成空的 vector 容器。该函数会改变 vector 的大小（变为 0），但不是改变其容量。
	
	*/
	std::vector<int> values{ 1,2,3,4,5 };
	auto first = values.begin();
	auto end = values.end();
	while (first != end)
	{
		std::cout << *first << " ";
		++first;
	}

	std::cout << "vector 容器首个元素地址: " << values.data()<<std::endl;
	values.push_back(20);
	std::cout << "当长度变化时首个元素地址: " << values.data()<<std::endl;

	std::cout << "当前size:" << values.size() << "当前容量:" << values.capacity();
	//删除元素 迭代器 第二个位置到倒数第三个位置
	values.erase(values.begin() + 1, values.end() - 2);
	std::cout << "当前size:" << values.size() << "当前容量:" << values.capacity();
}


void stlExample::testDeq() {
	std::deque<int> d;
	d.push_back(1);
	d.push_back(2);
	d.push_back(3);
	d.push_front(0);
/*
首先需要注意的一点是，迭代器的功能是遍历容器，在遍历的同时可以访问（甚至修改）容器中的元素，
但迭代器不能用来初始化空的 deque 容器。

 vector<int>values;
	auto first = values.begin();
	//*first = 1; 错误
对于空的 deque 容器来说，可以通过 push_back()、
push_front() 或者 resize() 成员函数实现向（空）deque 容器中添加元素。
*/
	std::cout << "deque元素个数:" << d.size()<<std::endl;
	for (auto i = d.begin(); i < d.end(); i++)
	{
		std::cout << *i << " ";
	}
	//常量迭代器 只可以访问当前元素，不能更改元素
	auto first = d.cbegin();
	auto end = d.cend();

	while (first<end)
	{
		std::cout << *first << " ";
		++first;

	}
	std::cout << std::endl;
	//反向迭代器用于以逆序的方式遍历容器中的元素
	for (auto i = d.rbegin(); i < d.rend(); i++) {
		std::cout << *i << " ";
	}
	
}

template <typename T> class Array
{
private:
	T* elements;
	size_t count;

public:
	explicit Array(size_t arraySize);
	Array(const Array& other);
	Array(Array&& other);
	virtual ~Array();
	T& operator[] (size_t index);
	const T& operator[] (size_t index) const;
	Array& operator=(const Array& rhs);
	Array& operator=(Array&& rhs);
	size_t size() {
		return count;
	}
};

int main()
{
	stlExample example;
	//example.testInsert();
	//example.testItera();
	//example.testArr();
	//20page
	//example.testVec();
	example.testDeq();
}

